using System;
using System.Collections.Generic;
using Cinemachine;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Pool;

namespace IQIGame.Onigao.GamePlay
{
    public class UnitCameraBehaviour : PlayableBehaviour
    {
        public string curvePath;
        public bool lookTarget;
        public int effectiveIndex;

        private double startTime = -1;
        private const float DefaultFov = 26.2f;

        private CameraCurveConfig cameraCofnig;
        private CinemachineVirtualCamera vc;
        private HashSet<UnitView> moveTargets = new HashSet<UnitView>();
        // private object role;

        public static ScriptPlayable<UnitCameraBehaviour> Create(PlayableGraph graph, GameObject gameObject)
        {
            if (gameObject == null)
                return ScriptPlayable<UnitCameraBehaviour>.Null;

            var handle = ScriptPlayable<UnitCameraBehaviour>.Create(graph);
            return handle;
        }

        public override void ProcessFrame(Playable playable, FrameData info, object playerData)
        {
            if (this.startTime < 0)
            {
                return;
            }
            if (playable.GetDuration() - playable.GetTime() < 0.01f)
            {
                this.EndMove();
            }
            else if (this.cameraCofnig == null)
            {
                this.StartMove(playerData);
            }
            else
            {
                var fCurTime = (float)playable.GetTime();
                this.SetCameraPos(fCurTime, playerData);
            }
        }

        public override void OnBehaviourPlay(Playable playable, FrameData info)
        {
            base.OnBehaviourPlay(playable, info);
            this.startTime = playable.GetTime();
        }

        public override void OnBehaviourPause(Playable playable, FrameData info)
        {
            base.OnBehaviourPause(playable, info);
            this.EndMove();
        }

        private void StartMove(object rRole)
        {
#if UNITY_EDITOR
            if (!Application.isPlaying && !SkillEditorMainUpdate.Instance.showCameraCurve)
            {
                return;
            }
#endif
            this.cameraCofnig = CameraCurveFactory.GetConfig(this.curvePath);

            if (this.cameraCofnig == null)
            {
                return;
            }
#if UNITY_EDITOR
            if (!Application.isPlaying)
            {
                SkillEditorMainUpdate.Instance.charaVc.gameObject.SetActive(true);
                this.vc = SkillEditorMainUpdate.Instance.charaVc;
            }
            else
#endif
            {
                this.vc = BattleManager.Instance.ctrl.sceneCtrl.vc_Character;
                BattleManager.Instance.ctrl.sceneCtrl.SetCameraState(BattleRenderSceneController.EBattleCameraState.Character);
            }
            var rRoleEntityDriver = rRole as EntityDriver;
            if (rRoleEntityDriver)
            {
                Transform rRoleFollow = null;

                var rSelfUnitView = BattleClientUtil.GetUnitViewByEntityDriver(rRoleEntityDriver);
                rSelfUnitView.GetComponent<BattleMoveComponent>(ETComponentType.BattleMoveComponent).TempMove();

#if UNITY_EDITOR
                if (!Application.isPlaying)
                {
                    rRoleFollow = SkillEditorMainUpdate.Instance.roleVcFollowRoot;
                }
                else
#endif
                {
                    rRoleFollow = BattleManager.Instance.ctrl.sceneCtrl.roleFollow;
                }

                Vector3 rRootPos = Vector3.zero;
                Quaternion rRootRot = Quaternion.identity;
                if (this.lookTarget)
                {
#if UNITY_EDITOR
                    if (!Application.isPlaying)
                    {
                        var rUnitView = SkillEditorMainUpdate.Instance.target;
                        if (rUnitView != null)
                        {
                            rRootPos = rUnitView.GetComponent<UnitViewComponent>(ETComponentType.UnitViewComponent).position;
                        }
                    }
                    else
#endif
                    {
                        var rUnitView = BattleClientUtil.GetUnitViewByEntityDriver(rRoleEntityDriver);
                        if (rUnitView != null)
                        {
                            // effectiveIndex 数据 1+， 0为默认
                            rRootPos = rUnitView.GetComponent<BattleTimelineComponent>(ETComponentType.BattleTimelineComponent).GetCurTargetPos(this.effectiveIndex);
                        }
                    }
                }
                else
                {
                    rRootPos = rRoleEntityDriver.transform.position;
                }
                rRootRot = rRoleEntityDriver.transform.rotation;

                if (this.lookTarget)
                {
                    //转180
                    Quaternion rotation = Quaternion.Euler(0, 180, 0);
                    rRootRot *= rotation;
                }

                rRoleFollow.position = rRootPos;
                rRoleFollow.rotation = rRootRot * this.cameraCofnig.rootRotation;
            }

            this.SetCameraPos(0, rRole);
        }

        private void EndMove()
        {
            if (this.cameraCofnig != null)
            {
#if UNITY_EDITOR
                if (!Application.isPlaying)
                {
                    SkillEditorMainUpdate.Instance.charaVc.gameObject.SetActive(false);
                    CameraCurveFactory.Clear();
                }
                else
#endif
                {
                    BattleManager.Instance.ctrl.sceneCtrl.ResetCamera();
                }
                this.vc = null;
            }
            foreach (var rTarget in this.moveTargets)
            {
                rTarget.GetComponent<BattleMoveComponent>(ETComponentType.BattleMoveComponent).Stop();
            }
            this.moveTargets.Clear();
            this.cameraCofnig = null;
        }

        private void SetCameraPos(float time, object role)
        {
            if (this.cameraCofnig == null)
            {
                return;
            }
            CameraCurveConfig.TryGetVector3(this.cameraCofnig.pos, time, out var rPos);
            CameraCurveConfig.TryGetQuaternion(this.cameraCofnig.rot, time, out var rRot);
            if (this.vc.Follow)
            {
                this.vc.Follow.localPosition = rPos;
                this.vc.Follow.localRotation = rRot;
            }
            var fFov = CameraCurveConfig.GetCurveValue(this.cameraCofnig.fov, time);
            this.vc.m_Lens.FieldOfView = fFov > 0 ? fFov : DefaultFov;

            var rRoleEntityDriver = role as EntityDriver;
            if (rRoleEntityDriver)
            {
                List<UnitView> rTargetTransList = ListPool<UnitView>.Get();
                var rSelfTrans = rRoleEntityDriver.transform;
                this.GetTargets(rRoleEntityDriver, ref rTargetTransList);
                var rSelfRot = rSelfTrans.rotation;
                for (int i = 0; i < rTargetTransList.Count; i++)
                {
                    var rTarget = rTargetTransList[i];
                    var rTargetTrans = rTarget.GetComponent<UnitViewComponent>(ETComponentType.UnitViewComponent).transform;
                    if (rTargetTrans)
                    {
                        if (this.cameraCofnig.targetPos?.Length > i &&
                            CameraCurveConfig.TryGetVector3(this.cameraCofnig.targetPos[i], time, out var rTargetPos))
                        {
                            if (this.moveTargets.Add(rTarget))
                            {
                                rTarget.GetComponent<BattleMoveComponent>(ETComponentType.BattleMoveComponent).TempMove();
                            }
                            rTargetPos = rSelfRot * rTargetPos;
                            rTargetTrans.localPosition = rTargetPos + rSelfTrans.position;
                        }
                        if (this.cameraCofnig.targetRot?.Length > i &&
                            CameraCurveConfig.TryGetQuaternion(this.cameraCofnig.targetRot[i], time, out var rTargetRot))
                        {
                            if (this.moveTargets.Add(rTarget))
                            {
                                rTarget.GetComponent<BattleMoveComponent>(ETComponentType.BattleMoveComponent).TempMove();
                            }
                            rTargetTrans.localRotation = rSelfRot * rTargetRot;
                        }
                    }
                }
                ListPool<UnitView>.Release(rTargetTransList);
            }
        }

        private void GetTargets(EntityDriver selfEntity, ref List<UnitView> list)
        {
#if UNITY_EDITOR
            if (BattleClientUtil.IsEditorMode)
            {
                var rUnitView = SkillEditorMainUpdate.Instance.target;
                if (rUnitView != null)
                {
                    list.Add(rUnitView);
                }
            }
            else
#endif
            if (selfEntity != null)
            {
                var rSelfUnitView = BattleClientUtil.GetUnitViewByEntityDriver(selfEntity);
                // effectiveIndex 数据 1+， 0为默认
                var rTargetList = rSelfUnitView.GetComponent<BattleTimelineComponent>(ETComponentType.BattleTimelineComponent).GetCurTarget(this.effectiveIndex);
                if (rTargetList?.Count > 0)
                {
                    for (int i = 0; i < rTargetList.Count; i++)
                    {
                        var rUnit = BattleManager.Instance.ctrl.data.GetUnit(rTargetList[i]);
                        list.Add(rUnit);
                    }
                }
            }
        }
    }
}